// 向量
// 两向量叉乘

export default class Vector2 {
    constructor() {

    }
    // 返回一个Vector2对象，x、y均为0。
    zero() {
        return [0, 0]
    }
    // clone(Vector2)：返回一个新的Vector2对象。
    clone(v1 = []) {
        return [...v1];
    }
    // 相等
    equals(v1 = [], v2 = []) {
        return v1.every((t, i) => t === v2[i])
    }

    // xy轴都大
    gt(v1 = [], v2 = []) {
        return v1.every((t, i) => t > v2[i])
    }
    lt(v1 = [], v2 = []) {
        return v1.every((t, i) => t < v2[i])
    }
    // 长度的平方
    sqrLength(v1 = []) {
        return v1.map(t => t * t).reduce((a, b) => a + b)
    }
    // 长度
    length(v1 = []) {
        return Math.sqrt(this.sqrLength(v1))
        // return Math.sqrt(v1.map(t => t * t).reduce((a, b) => a + b))
        // return Math.sqrt(v1[0] * v1[0] + v1[1] * v1[1]);
    }
    // 距离
    distance(v1 = [], v2 = []) {
        return Math.sqrt(this.sqrDistance(v1, v2))
    }

    // 距离的平方
    sqrDistance(v1 = [], v2 = []) {
        return v1.map((t, i) => (t - v2[i]) * (t - v2[i])).reduce((a, b) => a + b)
    }
    // 点积v1 · v2 = |a| * |b| * sin θ
    dot(v1 = [], v2 = []) {
        return v1.map((t, i) => t[i] * v2[i]).reduce((a, b) => a + b)
    }
    // 叉乘 v1 × v2 = |a| * |b| * sin θ
    cross(v1 = [], v2 = []) {
        return v1[0] * v2[1] - v1[1] * v2[0];
    }
    // 角度
    toAngle(v1 = []) {
        return Math.atan2(v1[1], v1[0]);
    }

    // 夹角
    angleTo(v1 = [], v2 = []) {
        return Math.atan2(v2[1] - v1[1], v2[0] - v1[0]);
    }

    // 大小比较
    magnitude(v1 = [], v2 = []) {
        let __x = v1[0] - v2[0];
        let __y = v1[1] - v2[1];

        return __x / __y;
    }

    // if v2 is between v1 and v3(inclusive)
    within(v1 = [], v2 = [], v3 = []) {
        return ((v1[0] <= v2[0] && v2[0] <= v3[0]) || (v3[0] <= v2[0] && v2[0] <= v1[0])) &&
            ((v1[1] <= v2[1] && v2[1] <= v3[1]) || (v3[1] <= v2[1] && v2[1] <= v1[1]));
    }
    //  if the distance between v1 and v2 is less than dist.
    near(v1, v2, dist) {
        // maybe inline
        let aux_number1 = this.sqrDistance(v1, v2);
        return aux_number1 < dist * dist;
    }

    //  * * 0 equal
    //  * * 1 top
    //     * * 2 top-right
    //     * * 3 right
    //     * * 4 bottom right
    //     * * 5 bottom
    //     * * 6 bottom-left
    //     * * 7 left
    //     * * 8 top-left
    compare(v1, v2) {
        var v1x = v1[0],
            v1y = v1[1],
            v2x = v2[0],
            v2y = v2[1];

        if (v2x === v1x && v2y === v1y) {
            return 0;
        }
        if (v2x === v1x) {
            return v2y > v1y ? 1 : 5;
        }
        if (v2y === v1y) {
            return v2x > v1x ? 3 : 7;
        }

        if (v2x > v1x) {
            if (v2y > v1y) {
                return 2;
            }

            if (v2y < v1y) {
                return 4;
            }
        }

        if (v2x < v1x) {
            if (v2y < v1y) {
                return 6;
            }
            if (v2y > v1y) {
                return 8;
            }
        }

        return -1;
    }

    // 反向
    negate(v1) {
        return v1.map(t => -t)
    }

    // 线性插值计算
    //  Linearly interpolate between a and b.
    lerp(v1, v2, d) {
        return v1.map((t, i) => t + (v2[i] - t) * d);
    }
    // multiply
    scale(v1, factor) {
        return v1.map(t => t * factor)
    }
    // 乘
    multiply(v1, v2) {
        return v1.map((t, i) => t * v2[i])
    }
    multiply2(v1, x, y) {
        return [v1[0] * x, v1[1] * y]
    }
    // 除
    divide(v1, v2) {
        return v1.map((t, i) => t / v2[i])
    }
    // 幂函数
    //  (x1^y, y1^y)
    pow(v1, y) {
        return v1.map(t => Math.pow(t, y))
    }
    max(v1, v2) {
        return v1.map((t, i) => Math.max(t, v2[i]))
    }
    min(v1, v2) {
        return v1.map((t, i) => Math.min(t, v2[i]))
    }
    abs(v1) {
        return v1.map(t => Math.abs(t))
    }

    scaleAndAdd(v1, v2, factor) {
        return v1.map((t, i) => t + v2[i] * factor)
    }

    clamp(v1, length) {
        if (this.dot(v1, v1) > length * length) {
            let out_vec2 = this.normalize(v1);
            return this.scale(out_vec2, length);
        }
        return v1;
    }

    // 向量单位
    normalize(v1) {
        let len = this.length(v1)
        if (len > Math.EPS) {
            return v1.map(t => t / len)
        }
    }
    truncate(v1, length) {
        if (this.sqrLength(v1) > length * length) {
            return this.scale(v1, length / this.length(v1))
        }
    }
    forAngle(radians) {
        return [Math.cos(radians), Math.sin(radians)]

    }

    // 投影
    project(v1, v2) {
        let v = this.multiply(v1, v2);
        return this.scale(v, this.dot(v1, v2) / this.dot(v2, v2));

    }

    rotate(v1, radians) {
        var s = Math.sin(radians),
            c = Math.cos(radians);

        let [x, y] = v1
        return [x * c - y * s, y * c + x * s]
    }

    // rotateFrom(out_vec2, v1, radians, center) {
    //     // subtract(out_vec2, v1, center);

    //     let __x = out_vec2[0];
    //     let __y = out_vec2[1];

    //     var s = Math.sin(radians),
    //         c = Math.cos(radians);


    //     out_vec2[0] = __x * c - __y * s;
    //     out_vec2[1] = __y * c + __x * s;

    //     // add(out_vec2, out_vec2, center);

    //     return out_vec2;
    // }
    // add(Vector2)：相加
    // addX(Vector2)：此x相加彼x
    // addY(Vector2)：此y相加彼y
    // addScalar(number)：x、y相加都加上number
    // addScalarX和addScalarY类似
    // 同理：sub——减法，multiply——加法，divide——除法

    // getMagnitude()：返回向量大小
    // normalize()：返回单位向量
    // randomize(Vector2):返回一个Vector2相关的随机向量
    // addRandom(number):加上一个number相关的随机向量
    // 同理：addRandomX，addRandomY

    // lerp(Vector2,number)：返回线性插值计算后的Vector2
    // 线性插值法
    //   线性插值是数学、计算机图形学等领域广泛使用的一种简单插值方法。 
    //   假设我们已知坐标(x0,y0)与(x1,y1),要得到[x0,x1]区间内某一位置x在直线上的值。根据图中所示，我们得到（y-y0）(x-x0)/(y1-y0)(x1-x0) 
    //   假设方程两边的值为α，那么这个值就是插值系数—从x0到x的距离与从x0到x1距离的比值。由于x值已知，所以可以从公式得到α的值 
    //   α=(x-x0)/(x1-x0) 
    //   同样，α=(y-y0)/(y1-y0) 
    //   这样，在代数上就可以表示成为： 
    //   y = (1- α)y0 + αy1 
    //   或者， 
    //   y = y0 + α(y1 - y0) 
    //   这样通过α就可以直接得到 y。实际上，即使x不在x0到x1之间并且α也不是介于0到1之间，这个公式也是成立的。在这种情况下，这种方法叫作线性外插—参见 外插值。 
    //   已知y求x的过程与以上过程相同，只是x与y要进行交换。
    // midpoint(Vector2)：返回两个点的中点Vector2
    // slope(Vector2)：得到斜率(number)
    // intercept(number):得到截距
    // distanceTo(Vector2)：得到距离(number)
    // angleTo(Vector2,string)：第二个参数为单位名称('rad','deg'),返回与Vector2之间的角度

}